package com.kx.my03;

import com.kx.my02.Student;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

import java.util.Date;

/**
 * @Aspect：是aspectj框架中的注解。 作用：表示当前类是切面类。
 * 切面类：是用来给业务方法增加功能的类，在这个类中有切面的功能代码
 */
@Aspect
public class MyAspect {
    /**
     * 环绕通知方法的定义要求：
     * 1、公共方法public
     * 2、方法必须有一个返回值，推荐使用Object
     * 3、方法名称自定义
     * 4、方法有参数的，固定的参数ProceedingJoinPoint
     */
    /**
     * @Around:环绕通知 属性：value切入点表达式
     * 特点：
     * 1、功能最强的通知，在目标方法的前后都能增强功能
     * 2、控制目标方法是否被调用执行
     * 3、能修改原来的目标方法的执行结果，影响最后的调用结果
     * 环绕通知等同于jdk动态代理，InvocationHandler接口
     * <p>
     * 参数：ProceedingJoinPoint等同于Method
     * 作用：执行目标方法的
     * 返回值：：就是目标方法的执行结果，可以被修改
     * 环绕通知：经常做事务，在目标方法前开启事务，执行目标方法，在目标方法后提交事务
     */
    @Around(value = "execution(* *..SomeServiceImpl.doFirst(..))")
    public Object myAround(ProceedingJoinPoint pjp) throws Throwable {
        String name = "";
        //获取第一个参数值
        Object[] args = pjp.getArgs();
        if (args != null && args.length > 1) {
            name = (String) args[0];
        }
        //实现环绕通知
        Object result = null;
        System.out.println("环绕通知：在目标方法之前，输出时间:" + new Date());
        //1、目标方法调用
        //2、在目标方法的前或者后加入功能
        if ("lisi".equals(name)) {
            result=pjp.proceed();   //等同于method.invoke();
        }
        System.out.println("环绕通知：在目标方法之前，提交事务");

        //修改目标方法的执行结果，影响方法最后的调用结果
        if (result!=null){
            result="Hello Around";
        }
        return result;
    }
}
